package com.wxh.clone;

import java.io.Serializable;

/**
 * @ClassName: ObjectCloneTest
 * @Description: 对象浅克隆和深克隆
 * @Author wxh
 * @Date: 2019/9/9 10:23
 * @Version V1.0.0
 * @Since 1.8
 */
public class ObjectCloneTest {
    public static void main(String[] args) throws CloneNotSupportedException {
        // 等号赋值，值类型
        int number = 6;
        int number2 = number;
        number2 = 9;
        System.out.println("-------------值类型复制--------------");
        System.out.println("number: "+number);
        System.out.println("number2: "+number2);
        // 用等号赋值对象,引用类型
        Dog dog = new Dog();
        dog.name = "旺财";
        dog.age = 5;
        // 克隆
        Dog dog2 = dog;
        dog2.name = "大白";
        dog2.age = 3;
        // 都是一样的值，因为指向同一个引用，改变一个，其他都改变，应该用克隆
        System.out.println("-------------引用类型复制，一改变都改变--------------");
        System.out.println(dog.name +", " + dog.age);
        System.out.println(dog2.name +", " + dog2.age);

        // 浅克隆--Object克隆方法，只拷贝值类型，没有拷贝引用类型
        Dog dog3 = (Dog) dog.clone();
        dog3.name = "小白";
        dog3.age = 2;
        System.out.println("-------------浅克隆--------------");
        System.out.println(dog.name +", " + dog.age);
        System.out.println(dog3.name +", " + dog3.age);

        DogChild dogChild = new DogChild();
        dogChild.name = "二狗";
        dog.dogChild = dogChild;
        Dog dog5 = (Dog) dog.clone();
        dog5.name = "大黄";
        dog5.dogChild.name = "狗二";
        // 都是一样的值，浅克隆存在问题：只复制值类型，不复制引用类型
        System.out.println("-------------浅克隆只是对象的值类型复制，引用类型不复制问题--------------");
        System.out.println("dog child name:"+dog.dogChild.name);
        System.out.println("dog5 child name:"+dog5.dogChild.name);

        // 使用序列化深度克隆对象
        Dog dog6 = CloneUtils.clone(dog);
        dog6.name = "黄雀";
        dog6.dogChild.name = "小黄雀";
        System.out.println("-------------序列化深度克隆--------------");
        System.out.println("dog child name:"+dog.dogChild.name);
        System.out.println("dog6 child name:"+dog6.dogChild.name);
    }
}

/**
 *  浅克隆：实现Cloneable接口
 *  值类型：在栈中分别分配一个存储空间
 *  引用类型：修改堆中公共的一个引用地址
 *
 */
class Dog implements Cloneable,Serializable{
    /**
     *  名字
     */
    public String name;
    /**
     *  年龄
     */
    public int age;
    /**
     *  dog子类
     */
    public DogChild dogChild;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

/**
 * 浅克隆存在问题：只复制值类型，不复制引用类型
 */
class DogChild implements Serializable{
    /**
     *  名字
     */
    public String name;
}
